// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

// 包含必要的头文件
#include "Components/GameFrameworkInitStateInterface.h"  // 游戏框架初始化状态接口
#include "Components/PawnComponent.h"                   //  pawn组件基类

#include "LyraPawnExtensionComponent.generated.h"       // UE生成的头文件

// 前向声明
namespace EEndPlayReason { enum Type : int; }           // 结束游戏原因枚举

class UGameFrameworkComponentManager;                   // 游戏框架组件管理器
class ULyraAbilitySystemComponent;                     // Lyra能力系统组件
class ULyraPawnData;                                   // Lyra pawn数据
class UObject;                                         // UE基础对象
struct FActorInitStateChangedParams;                   // 角色初始化状态改变参数
struct FFrame;                                         // 执行帧
struct FGameplayTag;                                   // 游戏标签

/**
 * 为所有Pawn类添加功能的组件，可用于角色/载具等
 * 这个组件协调其他组件的初始化
 */
UCLASS()
class LYRAGAME_API ULyraPawnExtensionComponent : public UPawnComponent, public IGameFrameworkInitStateInterface
{
	GENERATED_BODY()

public:
    // 构造函数
    ULyraPawnExtensionComponent(const FObjectInitializer& ObjectInitializer);

    /** 这个功能的名称，依赖于其他命名组件功能 */
    static const FName NAME_ActorFeatureName;

    //~ Begin IGameFrameworkInitStateInterface interface
    // 获取功能名称
    virtual FName GetFeatureName() const override { return NAME_ActorFeatureName; }
    // 检查是否可以改变初始化状态
    virtual bool CanChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState) const override;
    // 处理初始化状态改变
    virtual void HandleChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState) override;
    // 当角色初始化状态改变时调用
    virtual void OnActorInitStateChanged(const FActorInitStateChangedParams& Params) override;
    // 检查默认初始化
    virtual void CheckDefaultInitialization() override;
    //~ End IGameFrameworkInitStateInterface interface

    /** 如果指定actor上存在pawn扩展组件，则返回它 */
    UFUNCTION(BlueprintPure, Category = "Lyra|Pawn")
    static ULyraPawnExtensionComponent* FindPawnExtensionComponent(const AActor* Actor) { return (Actor ? Actor->FindComponentByClass<ULyraPawnExtensionComponent>() : nullptr); }

    /** 获取pawn数据，用于在数据中指定pawn属性 */
    template <class T>
    const T* GetPawnData() const { return Cast<T>(PawnData); }

    /** 设置当前pawn数据 */
    void SetPawnData(const ULyraPawnData* InPawnData);

    /** 获取当前能力系统组件，可能由其他actor拥有 */
    UFUNCTION(BlueprintPure, Category = "Lyra|Pawn")
    ULyraAbilitySystemComponent* GetLyraAbilitySystemComponent() const { return AbilitySystemComponent; }

    /** 应由拥有pawn调用，成为能力系统的化身 */
    void InitializeAbilitySystem(ULyraAbilitySystemComponent* InASC, AActor* InOwnerActor);

    /** 应由拥有pawn调用，移除自己作为能力系统的化身 */
    void UninitializeAbilitySystem();

    /** 当pawn的控制器改变时由拥有pawn调用 */
    void HandleControllerChanged();

    /** 当玩家状态已复制时由拥有pawn调用 */
    void HandlePlayerStateReplicated();

    /** 当输入组件设置完成时由拥有pawn调用 */
    void SetupPlayerInputComponent();

    /** 注册到OnAbilitySystemInitialized委托，如果pawn已注册到能力系统组件则广播 */
    void OnAbilitySystemInitialized_RegisterAndCall(FSimpleMulticastDelegate::FDelegate Delegate);

    /** 注册到OnAbilitySystemUninitialized委托，当pawn被移除为能力系统的化身actor时触发 */
    void OnAbilitySystemUninitialized_Register(FSimpleMulticastDelegate::FDelegate Delegate);

protected:
    // 重写组件生命周期函数
    virtual void OnRegister() override;
    virtual void BeginPlay() override;
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

    // 当PawnData被复制时调用
    UFUNCTION()
    void OnRep_PawnData();

    /** 当pawn成为能力系统的化身actor时触发的委托 */
    FSimpleMulticastDelegate OnAbilitySystemInitialized;

    /** 当pawn被移除为能力系统的化身actor时触发的委托 */
    FSimpleMulticastDelegate OnAbilitySystemUninitialized;

    /** 用于创建pawn的pawn数据。从生成函数或在放置的实例上指定 */
    UPROPERTY(EditInstanceOnly, ReplicatedUsing = OnRep_PawnData, Category = "Lyra|Pawn")
    TObjectPtr<const ULyraPawnData> PawnData;

    /** 指向能力系统组件的指针，为方便而缓存 */
    UPROPERTY()
    TObjectPtr<ULyraAbilitySystemComponent> AbilitySystemComponent;
};